#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include "common.h"
#include <string.h>
#include <errno.h>
#include "float_def.h"
#include <direct.h>
#include <math.h>
#include "lut.h"
#include <bitset>
#include <algorithm>
#include <vector>
#include <sstream>
#include <filesystem>

namespace fs = std::filesystem;

const char project_dir[] = "D:\\upixels\\zhoufc\\u31_instruction";

/**
 * 功能：创建u31工程
 * project_name:工程名
 * mem_upasm_file_name:u31内存文件
 * upinc_file_name:u31头文件
 * upasm_file_name:u31汇编文件
 * 返回值:0:成功, -1:失败
 */
int32_t creat_u31_project(const char *project_name, U31CodeFile &u31_code_file)
{
    const char mem_upasm_file_name[] = "app_memory.upasm";
    const char upinc_file_name[] = "app.upinc";
    const char upasm_file_name[] = "app.upasm";
    char project_path[256] = {0};
    char mem_upasm_file_path[256] = {0};
    char upinc_file_path[256] = {0};
    char upasm_file_path[256] = {0};

    snprintf(project_path, sizeof(project_path), "%s\\%s", project_dir, project_name);

    // 检查目录是否存在
    if (!fs::exists(project_path))
    {
        // 创建目录
        fs::create_directory(project_path);
        printf("directory created. path:%s\n", project_path);
    }

    snprintf(mem_upasm_file_path, sizeof(mem_upasm_file_path), "%s\\%s", project_path, mem_upasm_file_name);
    u31_code_file.mem_upasm_file = fopen(mem_upasm_file_path, "w");
    if (!u31_code_file.mem_upasm_file)
    {
        printf("open file failed. fname: %s\n", mem_upasm_file_path);
        return -1;
    }
    snprintf(upinc_file_path, sizeof(upinc_file_path), "%s\\%s", project_path, upinc_file_name);
    u31_code_file.upinc_file = fopen(upinc_file_path, "w");
    if (!u31_code_file.upinc_file)
    {
        printf("open file failed. fname: %s\n", upinc_file_path);
        return -1;
    }

    snprintf(upasm_file_path, sizeof(upasm_file_path), "%s\\%s", project_path, upasm_file_name);
    u31_code_file.upasm_file = fopen(upasm_file_path, "w");
    if (!u31_code_file.upasm_file)
    {
        printf("open file failed. fname: %s\n", upasm_file_path);
        return -1;
    }

    return 0;
}
/**
 * 功能: 关闭项目并释放资源
 * u31_code_file: 输入参数，包含要关闭的文件指针
 * 返回值: void
 */
void close_project(const U31CodeFile &u31_code_file)
{
    fclose(u31_code_file.mem_upasm_file);
    fclose(u31_code_file.upasm_file);
    fclose(u31_code_file.upinc_file);
    // fclose(u31_code_file.comm_upinc_file);
}
void gen_vector_upinc_label(FILE *file, const char *instruction, const char *label, int32_t case_num)
{
    if (!file)
    {
        printf("file is nulltpr!\n");
        return;
    }
    fprintf(file, "#import %s_case%d_%s\n", instruction, case_num, label);
}
void gen_vector_upasm_head_code(FILE *file, const char *instruction, int32_t case_num)
{
    if (!file)
    {
        printf("file is nulltpr!\n");
        return;
    }
    fprintf(file, "\n\n#include \"app.upinc\"\n\n");
    fprintf(file, "/*****************Register planning**************/\n");

    fprintf(file, "#define compare_times r11\n");
    fprintf(file, "#define compare_num r12\n");
    fprintf(file, "#define HAD_DIFF r13\n");

    fprintf(file, "\n\n/*****************program entry**************/\n\n");
    fprintf(file, "entry:\n\n");

    fprintf(file, "\n/*****************function define**************/\n");
    fprintf(file, "compare_func:\n");
    fprintf(file, "\tcache_clr\n");
    fprintf(file, "\tlc compare_times, 0\n");
    fprintf(file, "\twhileu compare_times < compare_num {\n");
    // fprintf(file, "\t\tsw r30, 0\n");
    fprintf(file, "\t\tnop\n");
    fprintf(file, "\t\tlw r0, ptr0\n");
    fprintf(file, "\t\tlw r1, ptr1\n");
    fprintf(file, "\t\tsub HAD_DIFF, r0, r1\n");
    // fprintf(file, "\t\tadd r20, r20, HAD_DIFF\n");
    // fprintf(file, "\t\tifu HAD_DIFF == 0 {\n");
    // fprintf(file, "\t\t\tspw r30, 1\n");
    // fprintf(file, "\t\t}\n");
    fprintf(file, "\t\tifu HAD_DIFF != 0 {\n");
    fprintf(file, "\t\t\thlt 0\n");
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t\tadd compare_times, compare_times, 1\n");
    fprintf(file, "\t}\n");
    // fprintf(file, "\tspw r30, 0\n");
    fprintf(file, "\tret\n\n\n");
}

void gen_vector_upasm_main_code(FILE *file, const char *instruction, int32_t case_num, const VectorParam &vp)
{
    if (!file)
    {
        printf("file is nulltpr!\n");
        return;
    }

    fprintf(file, "\t// %s test case%d\n", instruction, case_num);
    fprintf(file, "\tlc ptr0, %s_case%d_out\n", instruction, case_num);
    fprintf(file, "\tlc ptr1, %s_case%d_u31_out\n", instruction, case_num);
    // fprintf(file, "\tcall parser_param_func\n");

    fprintf(file, "\t// %s(flag, adr_in1, in1_mode, num, adr_in2, cmd_mode, in1_type, in2_en, in2_mode, in2_type, out_type, adr_out)\n", instruction);
    if (vp.in2_en && !vp.adr_in2)
        fprintf(file, "\t%s(%d, %s_case%d_in1, %d, %d, %s_case%d_in2, %d, %d, %d, %d, %d, %d, %s_case%d_u31_out)\n",
                instruction, vp.flag, instruction, case_num, vp.in1_mode, vp.num, instruction, case_num,
                vp.cmd_mode, vp.in1_type, vp.in2_en, vp.in2_mode, vp.in2_type, vp.out_type, instruction, case_num);
    else
        fprintf(file, "\t%s(%d, %s_case%d_in1, %d, %d, 0, %d, %d, %d, %d, %d, %d, %s_case%d_u31_out)\n",
                instruction, vp.flag, instruction, case_num, vp.in1_mode, vp.num, vp.cmd_mode, vp.in1_type,
                vp.in2_en, vp.in2_mode, vp.in2_type, vp.out_type, instruction, case_num);
    fprintf(file, "\tlc compare_num, %d\n", vp.out_size / 4);
    fprintf(file, "\thlt 14\n");
    fprintf(file, "\tcall compare_func\n\n");
}

/**
 * 功能: 生成U31代码文件
 * 参数:
 *   - u31_code_file: U31代码文件结构体
 *   - instruction: 指令名称
 *   - case_num: 测试用例编号
 *   - vp: 向量参数结构体
 * 返回值: 无
 */
void gen_u31_code(const U31CodeFile &u31_code_file, const char *instruction, int32_t case_num, const VectorParam &vp)
{
    if (!u31_code_file.mem_upasm_file || !u31_code_file.upasm_file || !u31_code_file.upinc_file)
    {
        printf("vector_mem_upasm_file is nullptr!\n");
        return;
    }
#if 0
    int32_t param_word[3] = {0};
    size_t pw_size = sizeof(param_word) / sizeof(param_word[0]);
    // set_bits(param_word[0], 0, 19, (int32_t)&vp.adr_in1);
    set_bits(param_word[0], 20, 22, (int32_t)vp.flag);
    // set_bits(param_word[1], 0, 19, (int32_t)&vp.adr_in2);
    set_bits(param_word[1], 20, 30, (int32_t)vp.num);
    set_bits(param_word[1], 31, 31, (int32_t)vp.in1_mode);
    // set_bits(param_word[2], 0, 19, (int32_t)&vp.adr_out);
    set_bits(param_word[2], 20, 20, (int32_t)vp.out_type);
    set_bits(param_word[2], 21, 22, (int32_t)vp.in2_type);
    set_bits(param_word[2], 23, 23, (int32_t)vp.in2_mode);
    set_bits(param_word[2], 24, 24, (int32_t)vp.in2_en);
    set_bits(param_word[2], 25, 26, (int32_t)vp.in2_type);
    set_bits(param_word[2], 27, 31, (int32_t)vp.cmd_mode);

    print_array(param_word, 3, "0x%08x");

#endif
    fprintf(u31_code_file.mem_upasm_file, "// %s test case%d\n", instruction, case_num);

    if (V_IN_TYPE_16 == vp.in1_type)
        gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "in1", case_num, (uint16_t *)vp.adr_in1, vp.num);
    else
        gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "in1", case_num, (uint32_t *)vp.adr_in1, vp.num);

    if (vp.in2_en && !vp.adr_in2)
    {
        if (V_IN_TYPE_16 == vp.in2_type)
            gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "in2", case_num, (uint16_t *)vp.adr_in2, vp.num);
        else
            gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "in2", case_num, (uint32_t *)vp.adr_in2, vp.num);
    }

    gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "out", case_num, (uint32_t *)vp.adr_out, vp.out_size / 4);
    gen_vector_mem_upsam_label(u31_code_file.mem_upasm_file, instruction, "u31_out", case_num, (uint32_t *)nullptr, 0);

    fprintf(u31_code_file.upinc_file, "// %s test case%d\n", instruction, case_num);
    gen_vector_upinc_label(u31_code_file.upinc_file, instruction, "in1", case_num);
    if (vp.in2_en && !vp.adr_in2)
        gen_vector_upinc_label(u31_code_file.upinc_file, instruction, "in2", case_num);
    gen_vector_upinc_label(u31_code_file.upinc_file, instruction, "out", case_num);
    gen_vector_upinc_label(u31_code_file.upinc_file, instruction, "u31_out", case_num);

    static int8_t first_write = 0;
    if (0 == first_write)
    {
        gen_vector_upasm_head_code(u31_code_file.upasm_file, instruction, case_num);
        first_write = 1;
    }

    gen_vector_upasm_main_code(u31_code_file.upasm_file, instruction, case_num, vp);
}
/**
 *  功能: 生成有序数组
 *  array: 输出参数, 输出数组
 *  array_size: 输入参数，数组大小
 *  start: 输入参数，有序数组的起始元素值
 *  interval: 输入参数，每个元素的间隔
 * 返回值: void
 */
void gen_array(Reg32 *array, size_t array_size, Reg32 start, S32 interval)
{
    for (size_t i = 0; i < array_size; i++)
    {
        array[i].sword = start.sword;
        start.sword += interval;
    }
}
/**
 * 功能: 用64bit数据表示0~15的随机数(每4bit表示一个数)
 * data: 输出参数
 * 返回值: void
 */
void random64(Reg64 *data)
{
    // 获取当前时间点
    auto now = std::chrono::high_resolution_clock::now();

    // 转换为自纪元以来的纳秒数
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch());

    srand(duration.count()); // 用当前时间初始化随机数种子

    // 生成0到15的随机数数组
    int numbers[16];
    for (int i = 0; i < 16; ++i)
    {
        numbers[i] = i; // 初始化为0到15
    }

    // 洗牌算法打乱数组
    for (int i = 15; i > 0; --i)
    {
        int j = rand() % (i + 1);
        int temp = numbers[i];
        numbers[i] = numbers[j];
        numbers[j] = temp;
    }

    // 将随机数赋值到64位数据中，每4位一个数字
    data->dword = 0;
    for (int i = 0; i < 16; ++i)
    {
        // 将数字转换为4位二进制，并左移至正确的位置
        data->dword |= (U64)numbers[i] << (60 - i * 4);
    }
}

/**
 * 功能:单精度浮点数据分解成8位指数和23位定点尾数
 * value:输入参数,需要分解的浮点数
 * e:8位指数部分
 * 返回值:23位定点尾数 规格化的为1.M,非规格化的为0.M
 * 非规格化数据真实尾数为0.M, 此处返回的是23为定点尾数M,8位指数部分为0,真实的指数为-126
 *  (非规格化数的指数字段全为0(二进制表示为00000000),在偏移表示法中,这表示实际指数为0-127,即-127.
 *  但是,IEEE754标准规定,非规格化数的实际指数为-126,而不是-127.这是因为非规格化数的表示范围要与规格化数的表示范围紧密衔接,
 *  以确保在接近零的区域有连续的数值表示)
 * 规格化数据的真实尾数为1.M, 此处返回的是23位定点尾数,即不包括整数1,
 * 真实指数为8位指数部分值-偏移量,设8位指数部分值为n,真实指数为n-127;
 */
int32_t frexpf_ext(float value, int32_t *exp)
{
    unsigned int *pValue = reinterpret_cast<unsigned int *>(&value);

    // 提取符号位
    // parts.sign = (*pValue >> 31) & 1;

    // 提取指数部分
    *exp = (*pValue >> 23) & 0xFF;

    // 提取尾数部分
    int32_t mantissa = *pValue & 0x7FFFFF;
    /**
     * 最小非规格化数:当尾数只有最后一个1(即二进制表示为0.00000000000000000000001)时，指数全为0，这表示数值为1*2^(-23)*2^(-126)
     * 最大非规格化数:当尾数全为1(即二进制表示为0.11111111111111111111111)时，指数全为0，这表示的数值大约为(1-2^(-23))*2^(-126)
     * 最小规格化数:当尾数全为0(即二进制表示为1.00000000000000000000000)时,尾数为1*2^0,指数部分的值为00000001(二进制),这表示数值为1.0*2^0*2^(1-127)=1.0*2^(-126)
     * 最大规格化:当尾数全为1(即二进制表示为0.11111111111111111111111)时,尾数为1*2^0 + (1-2^(-23)),即2-2^(-23),指数部分的值为11111110(二进制),这表示数值为(2-2^(-23))*2^(254-127)=(2-2^(-23))*2^127
     * 当指数部分的存储值为00000000或11111111时,该数不是规格化的,而是表示非规格化数或特殊值(如零、无穷大、NaN)
     * U31为方便处理,将规格化和非规格化数据的指数部分都统一到同一个指数偏移量127，则非规格化数据需将尾数左移移位
     */
    if (0 == *exp)
        mantissa <<= 1; // 非规格化数据左移1位
    else
        mantissa += 0x800000; // 规格化数据尾数为1.M

    return mantissa;
}

int64_t frexp_ext(double value, int32_t *exp)
{
    uint64_t *pValue = reinterpret_cast<uint64_t *>(&value); // 将双精度浮点数的位模式转换为uint64_t

    // 提取符号位（最高位）
    uint64_t sign = *pValue >> 63; // 符号位是最高位，右移63位

    // 提取指数位（接下来的11位）
    *exp = (*pValue >> 52) & 0x7FF; // 指数位是接下来的11位，与0x7FF做与操作以清除高位

    // 提取尾数（mantissa，除去隐含的前导1）
    int64_t mantissa = *pValue & 0xFFFFFFFFFFFFF; // 尾数是低52位

    if (0 == *exp)
        mantissa <<= 1; // 非规格化数据左移1位
    else
        mantissa += 0x10000000000000; // 规格化数据尾数为1.M
    return mantissa;
}

/**
 * 功能: 判断浮点数是否是无效数
 * hex: 浮点数的16进制
 * 返回值: true: 是无效值, false: 不是无效值
 */
bool is_nan(U32 hex)
{
    return ((f_qnan == hex) || (f_snan == hex));
}
/**
 * 功能: 判断浮点数是否是无穷大
 * hex: 浮点数的16进制
 * 返回值: true: 是无穷大, false: 不是无穷大
 */
bool is_inf(U32 hex)
{
    return ((f_infinity_n == hex) || (f_infinity == hex));
}
/**
 * 功能: 判断浮点数是否是0
 * hex: 浮点数的16进制
 * 返回值: true: 是, false: 不是
 */
bool is_zero(U32 hex)
{
    return ((f_0 == hex) || (f_0_n == hex));
}
/**
 * 功能: 浮点数16进制转浮点值
 * hex: 浮点数的16进制
 * 返回值: F32
 */
F32 hex_conv_f(U32 hex)
{
    F32 max_normal_n = *(float *)&hex;

    return max_normal_n;
}

/**
 * 功能: 判断浮点数是否是0
 * ff: 浮点数double
 * 返回值: true: 是, false: 不是
 */
bool is_zero_ff(double ff)
{
    int64_t *pValue = reinterpret_cast<int64_t *>(&ff);

    return ((*pValue & 0x7FFFFFFFFFFFFFFF) == 0);
}

/**
 * 功能: 判断浮点数是否是0
 * f: 浮点数float
 * 返回值: true: 是, false: 不是
 */
bool is_zero_f(float f)
{
    int32_t *pValue = reinterpret_cast<int32_t *>(&f);

    return ((*pValue & 0x7FFFFFFF) == 0);
}
/**
 * 功能: 获取函数名中的指令名
 * str: 输入参数, 函数名字符串
 * 返回值: 指令名字符串
 */
const char *get_instruction_from_func(const char *str)
{
    // 查找第一个下划线的索引
    const char *underscore = strchr(str, '_');
    if (underscore)
    {
        // 如果找到下划线，返回指向下划线之后字符的指针
        return underscore + 1;
    }
    else
    {
        // 如果没有找到下划线，返回原始字符串
        return str;
    }
}
/**
 * 功能: 在app_memory.upasm文件中定义操作数变量
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * idx: 输入参数, 操作数序号
 * data: 输入参数, 操作数数组
 * data_size: 输入参数, 操作数长度(占U32的个数)
 * opt_size: 输入参数, 操作数宽度(占U32的个数)
 * 返回值: void
 */
void gen_memupasm_input_data_lable(FILE *file, const char *instruction, U8 idx, const Reg32 *data, size_t data_size, size_t opt_size)
{
    if (NULL == file)
        return;
    if (1 == idx)
        fprintf(file, "\n// %s\n", instruction);
    fprintf(file, "#export %s_input_data%d\n%s_input_data%d:\n\t.word ", instruction, idx, instruction, idx);
    for (size_t i = 0; i < data_size + opt_size - 1; i++)
    {
        fprintf(file, "0x%08x ", data[i % data_size].word);
    }
    fprintf(file, "\n");
}

/**
 * 功能: 在app_memory.upasm文件中定义目的数变量
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * data: 输入参数, 操作数数组
 * data_size: 输入参数, 操作数长度(占U32的个数)
 * idx: 输入参数, 结果序号
 * 返回值: void
 */
void gen_mem_upasm_result_data_lable(FILE *file, const char *instruction, const Reg32 *data, size_t data_size, U8 idx)
{
    if (NULL == file)
        return;
    fprintf(file, "#export %s_result_data%u\n%s_result_data%u:\n\t.word ", instruction, idx, instruction, idx);
    for (size_t i = 0; i < data_size; i++)
    {
        fprintf(file, "0x%08x ", data[i].word);
    }
    fprintf(file, "\n");
}
/**
 * 功能: 在app_memory.upasm文件中定义存储对比不一致结果的buffer
 * file: 输入参数, 文件句柄
 * size: 输入参数, buffer大小(字节)
 * 返回值: void
 */
void gen_mem_upasm_diff_buffer_lable(FILE *file, U32 size)
{
    if (NULL == file)
        return;

    fprintf(file, "\n\n.align 16\n#export compare_diff_buffer\ncompare_diff_buffer:\n\t.reserve %d\n", size);
}
/**
 * 功能: 在app.upinc文件中声明存储对比不一致结果的buffer
 * file: 输入参数, 文件句柄
 * 返回值: void
 */
void gen_upinc_diff_buffer_lable(FILE *file)
{
    if (NULL == file)
        return;

    fprintf(file, "\n\n#import compare_diff_buffer\n");
}
/**
 * 功能: 在app.upinc文件中声明操作数变量
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * idx: 输入参数, 操作数序号
 * 返回值: void
 */
void gen_upinc_input_data_lable(FILE *file, const char *instruction, U8 idx)
{
    if (NULL == file)
        return;
    if (1 == idx)
        fprintf(file, "\n// %s\n", instruction);
    fprintf(file, "#import %s_input_data%u\n", instruction, idx);
}

/**
 * 功能: 在app.upinc文件中声明目的数变量
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * idx: 输入参数, 结果序号
 * 返回值: void
 */
void gen_upinc_result_data_lable(FILE *file, const char *instruction, U8 idx)
{
    if (NULL == file)
        return;
    fprintf(file, "#import %s_result_data%u\n", instruction, idx);
}
/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * opt1_size: 操作数1的宽度(相对4字节)
 * opt1_loop_cnt: 操作数1循环次数
 * dst_size: 目的数宽度(相对4字节)
 * dst_loop_cnt: 目的数2初始化循环次数
 */
void gen_upasm_1_op_init_dst_code(FILE *file, const char *instruction, size_t opt1_size, size_t opt1_loop_cnt, size_t dst_size, size_t dst_loop_cnt, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char dst_reg[5] = {0};
    char read_opt1_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};
    char init_result_cmd[12] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 4);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 4);
        strncpy(read_opt1_cmd, "l64", 4);
        strncpy(write_opt1_cmd, "s64", 4);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 4);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(init_result_cmd, "simd_add32", 11);
        strncpy(dst_reg, "r75", 4);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 4);
        strncpy(write_result_cmd, "s64", 4);
        strncpy(init_result_cmd, "add64", 5);
        strncpy(dst_reg, "r76", 4);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(init_result_cmd, "add", 4);
        strncpy(dst_reg, "r14", 4);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data1\n", instruction);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", opt1_loop_cnt * 4);

    fprintf(file, "\tlc r3, %s_input_data2\n", instruction);
    fprintf(file, "\tlc r16, 0\n");
    fprintf(file, "\tlc r15, %d\n", dst_loop_cnt * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");
#if SIMULATE_MACRO

    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\twhileu r5 < r4 {\n");
    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4);
    fprintf(file, "\t\tlc r16, 0\n");

    fprintf(file, "\t\twhileu r16 < r15 {\n");
    fprintf(file, "\t\t\tadd r8, r8, 1\n");
    fprintf(file, "\t\t\t%s %s, r3, r16\n", read_result_cmd, dst_reg);
    fprintf(file, "\t\t\t%s %s, %s, 0\n", init_result_cmd, u31_result_reg, dst_reg);
    fprintf(file, "\t\t\tadd r16, r16, %d\n", 4);
    //  fprintf(file, "\t\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t\t%s %s, %s\n", instruction, u31_result_reg, opt1_reg);
    fprintf(file, "\t\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO

    fprintf(file, "\t\t\tifu Diff_Num != 0 {\n");

    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, dst_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t\t}\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
}

/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * opt1_size: 操作数1的宽度(相对4字节)
 * opt1_loop_cnt: 操作数1循环次数
 * opt2_size: 操作数2的宽度(相对4字节)
 * opt2_loop_cnt: 操作数2循环次数
 * dst_size: 目的数宽度(相对4字节)
 * dst_loop_cnt: 目的数2初始化循环次数
 */
void gen_upasm_2_op_init_dst_code(FILE *file, const char *instruction, size_t opt1_size, size_t opt1_loop_cnt, size_t opt2_size, size_t opt2_loop_cnt, size_t dst_size, size_t dst_loop_cnt, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char opt2_reg[5] = {0};
    char dst_reg[5] = {0};
    char read_opt1_cmd[5] = {0};
    char read_opt2_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};
    char init_result_cmd[12] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_opt2_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_opt2_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 4);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 4);
        strncpy(read_opt1_cmd, "l64", 4);
        strncpy(write_opt1_cmd, "s64", 4);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 4);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }
    if (4 == opt2_size)
    {
        strncpy(opt2_reg, "r74", 4);
        strncpy(read_opt2_cmd, "lm", 3);
        strncpy(write_opt2_cmd, "sm", 3);
        write_opt2_pad = 0;
    }
    else if (2 == opt2_size)
    {
        strncpy(opt2_reg, "r66", 4);
        strncpy(read_opt2_cmd, "l64", 4);
        strncpy(write_opt2_cmd, "s64", 4);
        write_opt2_pad = 2;
    }
    else if (1 == opt2_size)
    {
        strncpy(opt2_reg, "r13", 4);
        strncpy(read_opt2_cmd, "lw", 3);
        strncpy(write_opt2_cmd, "sw", 3);
        write_opt2_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(init_result_cmd, "simd_add32", 11);
        strncpy(dst_reg, "r75", 4);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 4);
        strncpy(write_result_cmd, "s64", 4);
        strncpy(init_result_cmd, "add64", 5);
        strncpy(dst_reg, "r76", 4);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(init_result_cmd, "add", 4);
        strncpy(dst_reg, "r14", 4);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data1\n", instruction);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", opt1_loop_cnt * 4);

    fprintf(file, "\tlc r2, %s_input_data2\n", instruction);
    fprintf(file, "\tlc r7, 0\n");
    fprintf(file, "\tlc r6, %d\n", opt2_loop_cnt * 4);

    fprintf(file, "\tlc r3, %s_input_data3\n", instruction);
    fprintf(file, "\tlc r16, 0\n");
    fprintf(file, "\tlc r15, %d\n", dst_loop_cnt * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");
#if SIMULATE_MACRO

    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\twhileu r5 < r4 {\n");
    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4);
    fprintf(file, "\t\tlc r7, 0\n");

    fprintf(file, "\t\twhileu r7 < r6 {\n");
    fprintf(file, "\t\t\t%s %s, r2, r7\n", read_opt2_cmd, opt2_reg);
    fprintf(file, "\t\t\tadd r7, r7, %d\n", 4);
    fprintf(file, "\t\t\tadd r8, r8, 1\n");
    fprintf(file, "\t\t\tlc r16, 0\n");

    fprintf(file, "\t\t\twhileu r16 < r15 {\n");
    fprintf(file, "\t\t\t\t%s %s, r3, r16\n", read_result_cmd, dst_reg);
    fprintf(file, "\t\t\t\t%s %s, %s, 0\n", init_result_cmd, u31_result_reg, dst_reg);
    fprintf(file, "\t\t\t\tadd r16, r16, %d\n", 4);
    //  fprintf(file, "\t\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t\t\t%s %s, %s, %s\n", instruction, u31_result_reg, opt1_reg, opt2_reg);
    fprintf(file, "\t\t\t\tnop\n");
    fprintf(file, "\t\t\t\tnop\n");
    fprintf(file, "\t\t\t\tnop\n");

    fprintf(file, "\t\t\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\t\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO

    fprintf(file, "\t\t\t\tifu Diff_Num != 0 {\n");
    fprintf(file, "\t\t\t\t\t%s ptr1, %s\n", write_result_cmd, dst_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t\t\t%s ptr1, %s\n", write_opt2_cmd, opt2_reg);
    for (size_t i = 0; i < write_opt2_pad; i++)
    {
        fprintf(file, "\t\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t\t\t}\n");
#endif
    fprintf(file, "\t\t\t}\n");
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
}

/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * opt1_size: 操作数1的宽度(相对4字节)
 * a_size: 操作数1数据源的宽度(相对4字节)
 * a_interval: 从a数组中读取数据时, 每次间隔多少宽度(相对4字节)
 *  如：每次取8字节，int a[] = {1,2,3,4,5,6,7,8}
 *      a_interval=1: 第一次取出的是1,2，第二次取出的是2,3....
 *      a_interval=2: 第一次取出的是1,2, 第二次取出的是3,4....
 *      a_interval=3: 第一次取出的是1,2, 第二次取出的是4,5....
 * opt1_idx: 输入参数, opt1操作数序号
 * opt2_size: 操作数2的宽度(相对4字节)
 * b_size: 操作数2数据源的宽度(相对4字节)
 * b_interval: 从a数组中读取数据时, 每次间隔多少宽度(相对4字节)
 *  如：每次取8字节，int a[] = {1,2,3,4,5,6,7,8}
 *      b_interval=1: 第一次取出的是1,2，第二次取出的是2,3....
 *      b_interval=2: 第一次取出的是1,2, 第二次取出的是3,4....
 *      b_interval=3: 第一次取出的是1,2, 第二次取出的是4,5....
 * opt2_idx: 输入参数, opt2操作数序号
 * dst_size: 目的数宽度(相对4字节)
 */
void gen_upasm_2_op_muls64_64_code(FILE *file, const char *instruction,
                                   size_t opt1_size, size_t a_size, size_t a_interval, U8 opt1_idx,
                                   size_t opt2_size, size_t b_size, size_t b_interval, U8 opt2_idx,
                                   size_t dst_size, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char opt2_reg[5] = {0};
    char read_opt1_cmd[5] = {0};
    char read_opt2_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_opt2_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_opt2_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 3);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 3);
        strncpy(read_opt1_cmd, "l64", 3);
        strncpy(write_opt1_cmd, "s64", 3);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 3);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }
    if (4 == opt2_size)
    {
        strncpy(opt2_reg, "r74", 3);
        strncpy(read_opt2_cmd, "lm", 3);
        strncpy(write_opt2_cmd, "sm", 3);
        write_opt2_pad = 0;
    }
    else if (2 == opt2_size)
    {
        strncpy(opt2_reg, "r66", 3);
        strncpy(read_opt2_cmd, "l64", 3);
        strncpy(write_opt2_cmd, "s64", 3);
        write_opt2_pad = 2;
    }
    else if (1 == opt2_size)
    {
        strncpy(opt2_reg, "r13", 3);
        strncpy(read_opt2_cmd, "lw", 3);
        strncpy(write_opt2_cmd, "sw", 3);
        write_opt2_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 3);
        strncpy(write_result_cmd, "s64", 3);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data%u\n", instruction, opt1_idx);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", a_size * 4);

    fprintf(file, "\tlc r2, %s_input_data%u\n", instruction, opt2_idx);
    fprintf(file, "\tlc r7, 0\n");
    fprintf(file, "\tlc r6, %d\n", b_size * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");
#if SIMULATE_MACRO

    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\twhileu r5 < r4 {\n");

    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4 * a_interval);
    fprintf(file, "\t\tlc r7, 0\n");

    fprintf(file, "\t\twhileu r7 < r6 {\n");
    fprintf(file, "\t\t\t%s %s, r2, r7\n", read_opt2_cmd, opt2_reg);
    fprintf(file, "\t\t\tadd r7, r7, %d\n", 4 * b_interval);
    fprintf(file, "\t\t\tadd r8, r8, 1\n");

    //  fprintf(file, "\t\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t\t%s %s, %s, %s\n", instruction, u31_result_reg, opt1_reg, opt2_reg);
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO

    fprintf(file, "\t\t\tifu Diff_Num != 0 {\n");
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt2_cmd, opt2_reg);
    for (size_t i = 0; i < write_opt2_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t\t}\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
}

/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * reg_r38: 寄存器38的值
 * opt1_size: 操作数1的宽度(相对4字节)
 * opt1_loop_cnt: 操作数1循环次数
 * opt2_size: 操作数2的宽度(相对4字节)
 * opt2_loop_cnt: 操作数2循环次数
 * dst_size: 目的数宽度(相对4字节)
 */
void gen_upasm_2_op_atk_rls_code(FILE *file, const char *instruction, S32 reg_r38, size_t opt1_size, size_t opt1_loop_cnt, size_t opt2_size, size_t opt2_loop_cnt, size_t dst_size, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char opt2_reg[5] = {0};
    char read_opt1_cmd[5] = {0};
    char read_opt2_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_opt2_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_opt2_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 3);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 3);
        strncpy(read_opt1_cmd, "l64", 3);
        strncpy(write_opt1_cmd, "s64", 3);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 3);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }
    if (4 == opt2_size)
    {
        strncpy(opt2_reg, "r74", 3);
        strncpy(read_opt2_cmd, "lm", 3);
        strncpy(write_opt2_cmd, "sm", 3);
        write_opt2_pad = 0;
    }
    else if (2 == opt2_size)
    {
        strncpy(opt2_reg, "r66", 3);
        strncpy(read_opt2_cmd, "l64", 3);
        strncpy(write_opt2_cmd, "s64", 3);
        write_opt2_pad = 2;
    }
    else if (1 == opt2_size)
    {
        strncpy(opt2_reg, "r13", 3);
        strncpy(read_opt2_cmd, "lw", 3);
        strncpy(write_opt2_cmd, "sw", 3);
        write_opt2_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 3);
        strncpy(write_result_cmd, "s64", 3);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data1\n", instruction);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", opt1_loop_cnt * 4);

    fprintf(file, "\tlc r2, %s_input_data2\n", instruction);
    fprintf(file, "\tlc r7, 0\n");
    fprintf(file, "\tlc r6, %d\n", opt2_loop_cnt * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");
#if SIMULATE_MACRO
    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\tlc r38, 0x%08x\n", reg_r38);

    fprintf(file, "\twhileu r5 < r4 {\n");

    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4);
    fprintf(file, "\t\tlc r7, 0\n");

    fprintf(file, "\t\twhileu r7 < r6 {\n");
    fprintf(file, "\t\t\t%s %s, r2, r7\n", read_opt2_cmd, opt2_reg);
    fprintf(file, "\t\t\tadd r7, r7, %d\n", 4);
    fprintf(file, "\t\t\tadd r8, r8, 1\n");

    //  fprintf(file, "\t\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t\t%s %s, %s, %s\n", instruction, u31_result_reg, opt1_reg, opt2_reg);
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO

    fprintf(file, "\t\t\tifu Diff_Num != 0 {\n");
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt2_cmd, opt2_reg);
    for (size_t i = 0; i < write_opt2_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t\t}\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
}

/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * opt1_size: 操作数1的宽度(相对4字节)
 * opt1_loop_cnt: 操作数1循环次数
 * opt2_size: 操作数2的宽度(相对4字节)
 * opt2_loop_cnt: 操作数2循环次数
 * dst_size: 目的数宽度(相对4字节)
 */
void gen_upasm_2_op_code(FILE *file, const char *instruction, size_t opt1_size, size_t opt1_loop_cnt, size_t opt2_size, size_t opt2_loop_cnt, size_t dst_size, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char opt2_reg[5] = {0};
    char read_opt1_cmd[5] = {0};
    char read_opt2_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_opt2_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_opt2_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 3);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 3);
        strncpy(read_opt1_cmd, "l64", 3);
        strncpy(write_opt1_cmd, "s64", 3);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 3);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }
    if (4 == opt2_size)
    {
        strncpy(opt2_reg, "r74", 3);
        strncpy(read_opt2_cmd, "lm", 3);
        strncpy(write_opt2_cmd, "sm", 3);
        write_opt2_pad = 0;
    }
    else if (2 == opt2_size)
    {
        strncpy(opt2_reg, "r66", 3);
        strncpy(read_opt2_cmd, "l64", 3);
        strncpy(write_opt2_cmd, "s64", 3);
        write_opt2_pad = 2;
    }
    else if (1 == opt2_size)
    {
        strncpy(opt2_reg, "r13", 3);
        strncpy(read_opt2_cmd, "lw", 3);
        strncpy(write_opt2_cmd, "sw", 3);
        write_opt2_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 3);
        strncpy(write_result_cmd, "s64", 3);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data1\n", instruction);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", opt1_loop_cnt * 4);

    fprintf(file, "\tlc r2, %s_input_data2\n", instruction);
    fprintf(file, "\tlc r7, 0\n");
    fprintf(file, "\tlc r6, %d\n", opt2_loop_cnt * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");
#if SIMULATE_MACRO
    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\twhileu r5 < r4 {\n");

    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4);
    fprintf(file, "\t\tlc r7, 0\n");

    fprintf(file, "\t\twhileu r7 < r6 {\n");
    fprintf(file, "\t\t\t%s %s, r2, r7\n", read_opt2_cmd, opt2_reg);
    fprintf(file, "\t\t\tadd r7, r7, %d\n", 4);
    fprintf(file, "\t\t\tadd r8, r8, 1\n");

    //  fprintf(file, "\t\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t\t%s %s, %s, %s\n", instruction, u31_result_reg, opt1_reg, opt2_reg);
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\tnop\n");
    fprintf(file, "\t\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO
    fprintf(file, "\t\t\tifu Diff_Num != 0 {\n");
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_opt2_cmd, opt2_reg);
    for (size_t i = 0; i < write_opt2_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t\t}\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
}
/**
 * 功能: 在app.upasm文件中生成指定指令的测试代码
 * file: 输入参数, 文件句柄
 * instruction: 输入参数, 指令名
 * opt1_size: 操作数1的宽度(相对4字节)
 * opt1_loop_cnt: 操作数1循环次数
 * opt1_loop_interval: 操作数1循环间隔
 * dst_size: 目的数宽度(相对4字节)
 */
void gen_upasm_1_op_code(FILE *file, const char *instruction, size_t opt1_size, size_t opt1_loop_cnt, size_t dst_size, U8 res_idx)
{
    if (NULL == file)
        return;

    char opt1_reg[5] = {0};
    char read_opt1_cmd[5] = {0};

    char u31_result_reg[32] = {0};
    const char *u31_result_32bit_reg = "U31_Result_32bit";
    const char *u31_result_64bit_reg = "U31_Result_64bit";
    const char *u31_result_128bit_reg = "U31_Result_128bit";

    char correct_result_reg[32] = {0};
    const char *correct_result_32bit_reg = "Correct_Result_32bit";
    const char *correct_result_64bit_reg = "Correct_Result_64bit";
    const char *correct_result_128bit_reg = "Correct_Result_128bit";
    char read_result_cmd[5] = {0};

    char compare_func[32] = {0};
    const char *compare_func_32bit = "compare_32bit_func";
    const char *compare_func_64bit = "compare_64bit_func";
    const char *compare_func_128bit = "compare_128bit_func";

    char write_opt1_cmd[5] = {0};
    char write_result_cmd[5] = {0};

    U8 write_opt1_pad = 0;
    U8 write_result_pad = 0;

    if (4 == opt1_size)
    {
        strncpy(opt1_reg, "r73", 3);
        strncpy(read_opt1_cmd, "lm", 3);
        strncpy(write_opt1_cmd, "sm", 3);
        write_opt1_pad = 0;
    }
    else if (2 == opt1_size)
    {
        strncpy(opt1_reg, "r65", 3);
        strncpy(read_opt1_cmd, "l64", 3);
        strncpy(write_opt1_cmd, "s64", 3);
        write_opt1_pad = 2;
    }
    else if (1 == opt1_size)
    {
        strncpy(opt1_reg, "r12", 3);
        strncpy(read_opt1_cmd, "lw", 3);
        strncpy(write_opt1_cmd, "sw", 3);
        write_opt1_pad = 3;
    }

    if (4 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_128bit_reg, strlen(u31_result_128bit_reg));
        strncpy(correct_result_reg, correct_result_128bit_reg, strlen(correct_result_128bit_reg));
        strncpy(read_result_cmd, "lm", 3);
        strncpy(write_result_cmd, "sm", 3);
        strncpy(compare_func, compare_func_128bit, strlen(compare_func_128bit));
        write_result_pad = 0;
    }
    else if (2 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_64bit_reg, strlen(u31_result_64bit_reg));
        strncpy(correct_result_reg, correct_result_64bit_reg, strlen(correct_result_64bit_reg));
        strncpy(read_result_cmd, "l64", 3);
        strncpy(write_result_cmd, "s64", 3);
        strncpy(compare_func, compare_func_64bit, strlen(compare_func_64bit));
        write_result_pad = 2;
    }
    else if (1 == dst_size)
    {
        strncpy(u31_result_reg, u31_result_32bit_reg, strlen(u31_result_32bit_reg));
        strncpy(correct_result_reg, correct_result_32bit_reg, strlen(correct_result_32bit_reg));
        strncpy(read_result_cmd, "lw", 3);
        strncpy(write_result_cmd, "sw", 3);
        strncpy(compare_func, compare_func_32bit, strlen(compare_func_32bit));
        write_result_pad = 3;
    }

    fprintf(file, "\n\t// %s\n", instruction);
    fprintf(file, "\tlc r1, %s_input_data1\n", instruction);
    fprintf(file, "\tlc r5, 0\n");
    fprintf(file, "\tlc r4, %d\n", opt1_loop_cnt * 4);

    fprintf(file, "\tlc ptr0, %s_result_data%u\n", instruction, res_idx);
    fprintf(file, "\tlc ptr1, compare_diff_buffer\n");
    fprintf(file, "\tlc r8, 0\n");

#if SIMULATE_MACRO

    fprintf(file, "\tlc r9, 0\n");
    fprintf(file, "\tlc r10, 0xFFFFFFFF\n");
#endif
    fprintf(file, "\twhileu r5 < r4 {\n");

    fprintf(file, "\t\t%s %s, r1, r5\n", read_opt1_cmd, opt1_reg);
    fprintf(file, "\t\tadd r5, r5, %d\n", 4);
    fprintf(file, "\t\tadd r8, r8, 1\n");
    //     fprintf(file, "\t\t%s %s, 0\n", read_result_cmd, u31_result_reg);

    fprintf(file, "\t\t%s %s, %s\n", instruction, u31_result_reg, opt1_reg);
    fprintf(file, "\t\t%s %s, ptr0\n", read_result_cmd, correct_result_reg);
    fprintf(file, "\t\tcall %s\n", compare_func);
#if SIMULATE_MACRO

    fprintf(file, "\t\tifu Diff_Num != 0 {\n");
    fprintf(file, "\t\t\t%s ptr1, %s\n", write_opt1_cmd, opt1_reg);
    for (size_t i = 0; i < write_opt1_pad; i++)
    {
        fprintf(file, "\t\t\tsw ptr1, r10\n");
    }

    fprintf(file, "\t\t\t%s ptr1, %s\n", write_result_cmd, u31_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\t%s ptr1, %s\n", write_result_cmd, correct_result_reg);
    for (size_t i = 0; i < write_result_pad; i++)
    {
        fprintf(file, "\t\t\tsw ptr1, r10\n");
    }
    fprintf(file, "\t\t\tadd r9, r9, 1\n");
    fprintf(file, "\t\t}\n");
#endif
    fprintf(file, "\t}\n");
}
void gen_upasm_head_code(FILE *file)
{
    fprintf(file, "\n\n#include \"app.upinc\"\n");
    fprintf(file, "\n#define U31_Result_128bit r72 //保存U31 128bit结果\n");
    fprintf(file, "#define Correct_Result_128bit r79 //保存128bit正确值\n");
    fprintf(file, "#define U31_Result_64bit r64 //保存U31 64bit结果\n");
    fprintf(file, "#define Correct_Result_64bit r71 //保存64bit正确值\n");
    fprintf(file, "#define U31_Result_32bit r0 //保存U31 32bit结果\n");
    fprintf(file, "#define Correct_Result_32bit r31 //保存32bit正确值\n");
    fprintf(file, "#define Compare_Result_Reg r30 // 保存比较结果\n");
    fprintf(file, "#define Cycle_Num r32 //保存有差异的Cycle_Index之和\n");
    fprintf(file, "#define Word_Tmp1 r33 //保存U31的word\n");
    fprintf(file, "#define Word_Tmp2 r34 //保存Correct的word\n");
    fprintf(file, "#define Diff_Num r35 //U31和Correct有几个word不一致\n");
    fprintf(file, "#define Word_Diff r36 //保存U31的word减Correct的word值,不能用r61\n");
    fprintf(file, "#define Word_Index r37 //保存rd32指令的立即数\n");
    fprintf(file, "#define Cycle_Index r38 //保存循环标志位\n");
    fprintf(file, "\nentry:\n\tlc r0, 0x0900003c\n\tsw r0, 0\n\tlc r50, 0x09000b08\n\tsw r50, 0\n\tlc r0, 0x09000b04\n\tsw r0, 0x1f\n");
}
void gen_upasm_tail_code(FILE *file)
{
    fprintf(file, "\n\tlc r50, 0x09000b08\n\tsw r50, 0x1f\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tsw r50, 0\n\thlt 0\n");

    fprintf(file, "\ncompare_128bit_func:\n");
    fprintf(file, "\n\tlc Diff_Num, 0\n\tlc Word_Diff, 0\n\tlc Word_Index, 0\n\tlc Cycle_Index, 0\n");
    fprintf(file, "\twhileu Cycle_Index < 4 {\n");
    fprintf(file, "\t\trd32 Word_Tmp1, U31_Result_128bit, Word_Index\n");
    fprintf(file, "\t\trd32 Word_Tmp2, Correct_Result_128bit, Word_Index\n");
    fprintf(file, "\t\tadd Word_Index, Word_Index, 1\n");
    fprintf(file, "\t\tadd Cycle_Index, Cycle_Index, 1\n");
    fprintf(file, "\t\tsub Word_Diff, Word_Tmp1, Word_Tmp2 //U31的word-Correct的word结果判断是否一致\n");
    fprintf(file, "\t\tifu Word_Diff != 0 {\n");
    fprintf(file, "\t\t\tadd Diff_Num, Diff_Num, 1\n");
#if !SIMULATE_MACRO
    fprintf(file, "\t\t\thlt 0\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
    fprintf(file, "\tret\n");

    fprintf(file, "\ncompare_64bit_func:\n");
    fprintf(file, "\n\tlc Diff_Num, 0\n\tlc Word_Diff, 0\n\tlc Word_Index, 0\n\tlc Cycle_Index, 0\n\tlc Cycle_Num, 0\n");
    fprintf(file, "\tsimd_1bit_to_2bit U31_Result_128bit, U31_Result_64bit //扩展为128bit\n");
    fprintf(file, "\tsimd_1bit_to_2bit Correct_Result_128bit, Correct_Result_64bit //扩展为128bit\n");
    fprintf(file, "\twhileu Cycle_Index < 4 {\n");
    fprintf(file, "\t\trd32 Word_Tmp1, U31_Result_128bit, Word_Index\n");
    fprintf(file, "\t\trd32 Word_Tmp2, Correct_Result_128bit, Word_Index\n");
    fprintf(file, "\t\tadd Word_Index, Word_Index, 1\n");
    fprintf(file, "\t\tadd Cycle_Index, Cycle_Index, 1\n");
    fprintf(file, "\t\tsub Word_Diff, Word_Tmp1, Word_Tmp2 //U31的word-Correct的word结果判断是否一致\n");
    fprintf(file, "\t\tifu Word_Diff != 0 {\n");
    fprintf(file, "\t\t\tadd Cycle_Num, Cycle_Num, Cycle_Index\n");
    fprintf(file, "\t\t\tadd Diff_Num, Diff_Num, 1\n");
#if !SIMULATE_MACRO
    fprintf(file, "\t\t\thlt 0\n");
#endif
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");
    fprintf(file, "\tifu Diff_Num == 4 {\n");
    fprintf(file, "\t\tlc Diff_Num, 2\n");
    fprintf(file, "\t}\n");
    fprintf(file, "\tifu Diff_Num == 3 {\n");
    fprintf(file, "\t\tlc Diff_Num, 2\n");
    fprintf(file, "\t}\n");
    fprintf(file, "\tifu Diff_Num == 2 {\n");
    fprintf(file, "\t\tifu Cycle_Num == 3 {\n");
    fprintf(file, "\t\t\tlc Diff_Num, 1\n");
    fprintf(file, "\t\t} else {\n");

    fprintf(file, "\t\t\tifu Cycle_Num == 7 {\n");
    fprintf(file, "\t\t\t\tlc Diff_Num, 1\n");
    fprintf(file, "\t\t\t} else {\n");
    fprintf(file, "\t\t\t\tlc Diff_Num, 2\n");
    fprintf(file, "\t\t\t}\n");
    fprintf(file, "\t\t}\n");
    fprintf(file, "\t}\n");

    fprintf(file, "\tifu Diff_Num == 1 {\n");
    fprintf(file, "\t\tlc Diff_Num, 1\n");
    fprintf(file, "\t}\n");
    fprintf(file, "\tret\n");

    fprintf(file, "\ncompare_32bit_func:\n");
    fprintf(file, "\n\tlc Diff_Num, 0\n");
    fprintf(file, "\tsub Word_Diff, U31_Result_32bit, Correct_Result_32bit //U31的word-Correct结果判断是否一致\n");
    fprintf(file, "\tifu Word_Diff != 0 {\n");
    fprintf(file, "\t\tadd Diff_Num, Diff_Num, 1\n");
#if !SIMULATE_MACRO
    fprintf(file, "\t\thlt 0\n");
#endif
    fprintf(file, "\t}\n");
    fprintf(file, "\tret\n");
}
/**
 * 功能: 设置操作数
 * opt: 输出参数, 操作数
 * opt_size：输入参数, 操作数宽度
 * data: 输入参数, 测试数据源数组
 * data_size: 输入参数, 测试数据源数组长度
 * index: 循环设置操作数opt索引
 * 返回值: true: 设置成功, false: 设置失败
 */
bool set_opt(void *opt, size_t opt_size, const Reg32 *data, size_t data_size, U32 index)
{
    if (4 == opt_size)
    {
        Reg128 *opt_ptr = (Reg128 *)opt;
        for (size_t i = 0; i < opt_size; i++)
        {
            opt_ptr->word[i] = data[(index + i) % data_size].word;
        }
        return true;
    }
    if (2 == opt_size)
    {
        Reg64 *opt_ptr = (Reg64 *)opt;
        for (size_t i = 0; i < opt_size; i++)
        {
            opt_ptr->word[i] = data[(index + i) % data_size].word;
        }
        return true;
    }
    if (1 == opt_size)
    {
        Reg32 *opt_ptr = (Reg32 *)opt;
        opt_ptr->word = data[index % data_size].word;
        return true;
    }
    return false;
}
/**
 * 功能: 设置操作数
 * res: 输出参数, 存储所有结果数组
 * max_res_size：输入参数, 结果数组大小
 * index: 结果数组res索引
 * dst: 输入参数, 目的数
 * data_size: 输入参数, 目的数宽度
 * 返回值: true: 设置成功, false: 设置失败
 */
bool set_result(Reg32 *res, size_t max_res_size, size_t *index, const void *dst, size_t dst_size)
{
    size_t idx = *index;
    if (4 == dst_size)
    {
        Reg128 *dst_ptr = (Reg128 *)dst;
        for (size_t i = 0; i < dst_size && idx < max_res_size; i++)
        {
            res[idx++].word = dst_ptr->word[i];
        }
        *index = idx;
        return true;
    }
    if (2 == dst_size)
    {
        Reg64 *dst_ptr = (Reg64 *)dst;
        for (size_t i = 0; i < dst_size && idx < max_res_size; i++)
        {
            res[idx++].word = dst_ptr->word[i];
        }
        *index = idx;
        return true;
    }
    if (1 == dst_size)
    {
        Reg32 *dst_ptr = (Reg32 *)dst;
        if (idx < max_res_size)
        {
            res[idx++].word = dst_ptr->word;
        }
        *index = idx;
        return true;
    }
    return false;
}

/** 提取两个相乘后的符号 0:+ 1:-*/
unsigned char float_mul_sign(int a, int b)
{
    return ((a >> 31) ^ (b >> 31)); // 0+ 1-
}
/** 计算特殊值浮点加,至少有一个乘数为inf或nan */
int float_add_special(int a, int b)
{
    if (is_nan(a) || is_nan(b))
        return f_qnan;
    if (is_inf(a) && is_inf(b) && float_mul_sign(a, b))
        return f_qnan;

    return is_inf(a) ? a : b; // a b 必有一个为inf
}

/** 计算特殊值浮点减,至少有一个乘数为inf或nan */
int float_sub_special(int a, int b)
{
    if (is_nan(a) || is_nan(b))
        return f_qnan;
    if (is_inf(a) && is_inf(b) && !float_mul_sign(a, b))
        return f_qnan;

    return is_inf(a) ? a : (f_infinity == b ? f_infinity_n : f_infinity); // a b 必有一个为inf a不为inf时,返回-b
}
/** 计算inf浮点乘,至少有一个乘数为inf */
int float_mul_inf(int a, int b)
{
    if ((is_inf(a) && is_zero(b)) || (is_inf(b) && is_zero(a)))
        return f_qnan;
    else
        return float_mul_sign(a, b) ? f_infinity_n : f_infinity;
}
/** 计算inf浮点乘减ac-bd,至少有一个乘数为inf*/
int float_mulsub_inf(int a, int b, int c, int d)
{
    int ac = 0x0, bd = 0x0;
    if (is_inf(a) || is_inf(c))
    {
        ac = float_mul_inf(a, c);
    }
    if (is_inf(b) || is_inf(d))
    {
        bd = float_mul_inf(b, d);
    }
    return float_sub_special(ac, bd);
}
/** 计算inf浮点乘加bc+ad,至少有一个乘数为inf*/
int float_muladd_inf(int b, int a, int c, int d)
{
    int bc = 0x0, ad = 0x0;
    if (is_inf(b) || is_inf(c))
    {
        bc = float_mul_inf(b, c);
    }
    if (is_inf(a) || is_inf(d))
    {
        ad = float_mul_inf(a, d);
    }
    return float_add_special(bc, ad);
}
/** 浮点乘复数乘处理特殊值*/
bool handle_special_data_fmulc(int a, int b, int c, int d, int &real, int &imag)
{
    if (is_nan(a) || is_nan(b) || is_nan(c) || is_nan(d))
    {
        real = f_qnan;
        imag = f_qnan;
        return true;
    }
    if (is_inf(a) || is_inf(b) || is_inf(c) || is_inf(d))
    {
        real = float_mulsub_inf(a, b, c, d); // ac - bd
        imag = float_muladd_inf(b, a, c, d); // bc + ad
        return true;
    }

    return false;
}
/** 浮点乘加 特殊值处理*/
bool handle_special_data_fmuladd(int a, int b, int c, int &sum)
{
    if (is_nan(a) || is_nan(b) || is_nan(c))
    {
        sum = f_qnan;
        return true;
    }
    if (is_inf(a) || is_inf(b))
    {
        if ((is_inf(a) && is_zero(b)) || (is_inf(b) && is_zero(a))) // 0 * inf = nan
        {
            sum = f_qnan;
            return true;
        }
        else
        {
            int ab = ((a >> 31) ^ (b >> 31)) ? f_infinity_n : f_infinity;
            if (is_inf(c) && ((ab >> 31) ^ (c >> 31))) // c + ab 正负无穷相加
            {
                sum = f_qnan;
                return true;
            }
            sum = ab;
            return true;
        }
    }
    if (is_inf(c))
    {
        sum = c;
        return true;
    }
    if (is_zero(a) || is_zero(b))
    {
        if (0 == ((a >> 31) ^ (b >> 31)))
        {
            if (f_0_n == c) // -0 + 0 = 0   只有这一种情况 sum取值不等于c
            {
                sum = f_0;
                return true;
            }
        }
        Reg32 tmp = {0};
        tmp.sword = c;
        if ((0 < tmp.f && tmp.f < hex_conv_f(f_min_normal)) || (tmp.f < 0 && hex_conv_f(f_min_normal_n) < tmp.f)) // 非规格化数直接置零,保留符号
        {
            tmp.sword = (tmp.sword >> 31) ? (f_0_n) : (f_0);
        }
        sum = tmp.sword;
        return true;
    }

    return false;
}
/** 浮点乘减 特殊值处理*/
bool handle_special_data_fmulsub(int a, int b, int c, int &diff)
{
    if (is_nan(a) || is_nan(b) || is_nan(c))
    {
        diff = f_qnan;
        return true;
    }
    if (is_inf(a) || is_inf(b))
    {
        if ((is_inf(a) && is_zero(b)) || (is_inf(b) && is_zero(a))) // 0 * inf = nan
        {
            diff = f_qnan;
            return true;
        }
        else
        {
            int ab = ((a >> 31) ^ (b >> 31)) ? f_infinity_n : f_infinity;
            if (is_inf(c) && (0 == ((ab >> 31) ^ (c >> 31)))) // c - ab 相同符号无穷相减等于无效值
            {
                diff = f_qnan;
                return true;
            }
            diff = (f_infinity_n == ab) ? f_infinity : f_infinity_n;    // diff等于-ab,符号反一下
            return true;
        }
    }
    if (is_inf(c))
    {
        diff = c;
        return true;
    }
    if (is_zero(a) || is_zero(b))
    {
        if (((a >> 31) ^ (b >> 31)))
        {
            if (f_0_n == c) // -0 + 0 = 0
            {
                diff = f_0;
                return true;
            }
        }
        Reg32 tmp = {0};
        tmp.sword = c;
        if ((0 < tmp.f && tmp.f < hex_conv_f(f_min_normal)) || (tmp.f < 0 && hex_conv_f(f_min_normal_n) < tmp.f)) // 非规格化数直接置零,保留符号
        {
            tmp.sword = (tmp.sword >> 31) ? (f_0_n) : (f_0);
        }
        diff = tmp.sword;
        return true;
    }

    return false;
}
